import * as THREE from 'three';
import { ThreeRender } from '@/components/Warm/SDK/three';
import chinaJson from '@/assets/map/china.json';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

type MusicConfigType = {
    isOpenGUI?: boolean,
    useCanvasHeightAndWidth?: boolean
} 
export class Map extends ThreeRender {
    private controls: OrbitControls;

    constructor(el: Element, config?: MusicConfigType) {
        super(el, { useCanvasHeightAndWidth: !!config?.useCanvasHeightAndWidth });
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);
        this.initMap();
        this.setControls();
        this.setCamera();
        this.setLight();
        this.setScene();
        this.setRenderer();
        this.animate();
    }

    public initMap() {
        chinaJson.features.forEach((elem: any, index: any) => {
            // 定一个省份3D对象
            const province = new THREE.Object3D();
            // 每个的 坐标 数组
            const { coordinates } = elem.geometry;

            coordinates.forEach((multiPolygon: any[]) => {
                multiPolygon.forEach((polygon: any) => {
                    const shape = new THREE.Shape();

                    for (let i = 0; i < polygon.length; i++) {
                        let [x, y]: any = this.projection(polygon[i]);
                        if (i === 0) {
                            shape.moveTo(x, -y);
                        }
                        shape.lineTo(x, -y);
                    }

                    const extrudeSettings = {
                        depth: 4,
                        bevelEnabled: true,
                        bevelSegments: 1,
                        bevelThickness: 0.2
                    };

                    const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

                    // 平面部分材质
                    const material = new THREE.MeshStandardMaterial( {
                        metalness: 1,
                        color: 'pink',
                    } );
                    // 拉高部分材质
                    const material1 = new THREE.MeshStandardMaterial( {
                        metalness: 1,
                        roughness: 1,
                        color: '#fad',
                    } );

                    const mesh = new THREE.Mesh(geometry, [
                        material,
                        material1
                    ]);
                    // 设置高度将省区分开来
                    if (index % 2 === 0) {
                        mesh.scale.set(1, 1, 1.2);
                    }
                    // 给mesh开启阴影
                    mesh.castShadow = true;
                    mesh.receiveShadow = true;
                    province.add(mesh);
                });
            });
            this.scene.add(province);
        });
    }

    private setLight() {
        const light = new THREE.DirectionalLight( 0xffffff, 1 );
        light.position.set( 20, -50, 20 );
        light.castShadow = true;
        light.shadow.mapSize.width = 1024;
        light.shadow.mapSize.height = 1024;
        this.scene.add(light);
    }

    private setScene() {
        // 设置场景背景色
        // this.scene!.background = new THREE.Color('skyblue');
    }

    private animate(): void {
        requestAnimationFrame(this.animate.bind(this));
        this.checkRender(() => {
            this.controls.update();
            this.renderer!.render(this.scene!, this.camera!);
        });
    }

    private setRenderer() {
        this.renderer.setClearAlpha(0);
        // 色调映射
        this.renderer!.toneMapping = THREE.CustomToneMapping;
        // 色调曝光度
        this.renderer!.toneMappingExposure = 1.25;
        // 是否开启阴影渲染
        this.renderer!.shadowMap.enabled = true;
        // 阴影类型
        this.renderer!.shadowMap.type = THREE.PCFSoftShadowMap;
        // 输出编码格式
        this.renderer!.outputColorSpace = THREE.SRGBColorSpace;
        // 在renderer里面设置背景色
        this.renderer!.setClearColor(0xffffff, 0);
    }

    private setControls() {
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        this.controls.enableDamping = true;
        //动态阻尼系数 就是鼠标拖拽旋转灵敏度
        this.controls.dampingFactor = 0.25;
        //是否可以缩放
        this.controls.enableZoom = true;
        //设置相机距离原点的最远距离
        this.controls.minDistance = 1;
        //设置相机距离原点的最远距离
        this.controls.maxDistance = 200;
        //是否开启右键拖拽
        this.controls.enablePan = false;
    }

    private setCamera() {
        // 设置相机
        this.camera!.position.set(0, -50, 50);
        // 设置观看中心点
        this.camera!.lookAt(0, 0, 0);
    }
}